﻿#region Using Statements
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace StarFoxLauncher
{
    /// <summary>
    /// Application launcher.
    /// </summary>
    public partial class Launcher : Form
    {
        #region Default Settings

        // display resolution
        int defaultReslIndex;

        // start game in full screen / windowed mode...
        // ... by default, full screen mode
        const bool defaultDisplayMode = true;

        // antialiasing, postprocessing...
        // ... by default, active
        const bool defaultAntiAliasing = true;
        const bool defaultPostProcessing = true;

        // display modes supported by the system
        List<DisplayResolution> systemDisplayResl = new List<DisplayResolution>();

        /// <summary>
        /// Gets the supported display resolution modes available for the game.
        /// <para>It also sets the default display resolution mode used at game startup.</para>
        /// </summary>
        public void GetDisplayModes()
        {
            // obtain all supported display modes by the systen
            foreach (DisplayMode mode in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes)
                // select only 32 bit color format
                if (mode.Format == SurfaceFormat.Color)
                {
                    DisplayResolution config = new DisplayResolution(mode.Width, mode.Height);
                    systemDisplayResl.Add(config);
                }

            // obtain the default resolution... it's normally the last item in the list
            defaultReslIndex = systemDisplayResl.Count - 1;
        }

        #endregion

        #region Load Settings

        readonly string settingsFile = "StarFoxSettings.xml";

        // display settings loaded correctly
        bool isLoadOk;

        // loaded settings
        int loadReslIndex;
        bool loadDisplayMode;
        bool loadAntiAliasing;
        bool loadPostProcessing;

        private void LoadSettings()
        {
            isLoadOk = false;

            if (!File.Exists(settingsFile))
                return;

            using (XmlReader reader = XmlReader.Create(settingsFile))
            {
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element && reader.Name == "settings")
                    {
                        isLoadOk = true;
                        break;
                    }
                }

                if (!isLoadOk)
                    return;
                else
                    isLoadOk = false;

                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element && reader.Name == "launcher")
                    {
                        isLoadOk = true;
                        break;
                    }
                }

                if (!isLoadOk)
                    return;
                else
                    isLoadOk = false;

                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element && reader.Name == "reslindex")
                    {
                        reader.Read();
                        if (reader.NodeType == XmlNodeType.Text)
                        {
                            try
                            {
                                loadReslIndex = Convert.ToInt32(reader.Value);
                            }
                            catch
                            {
                                return;
                            }

                            if ((loadReslIndex >= 0) && (loadReslIndex <= systemDisplayResl.Count - 1))
                            {
                                isLoadOk = true;
                                break;
                            }
                        }
                    }
                }

                if (!isLoadOk)
                    return;
                else
                    isLoadOk = false;

                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element && reader.Name == "isfullscr")
                    {
                        reader.Read();
                        if (reader.NodeType == XmlNodeType.Text)
                        {
                            try
                            {
                                loadDisplayMode = Convert.ToBoolean(reader.Value);
                            }
                            catch
                            {
                                return;
                            }

                            isLoadOk = true;
                            break;
                        }
                    }
                }

                if (!isLoadOk)
                    return;
                else
                    isLoadOk = false;

                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element && reader.Name == "isantialiasing")
                    {
                        reader.Read();
                        if (reader.NodeType == XmlNodeType.Text)
                        {
                            try
                            {
                                loadAntiAliasing = Convert.ToBoolean(reader.Value);
                            }
                            catch
                            {
                                return;
                            }

                            isLoadOk = true;
                            break;
                        }
                    }
                }

                if (!isLoadOk)
                    return;
                else
                    isLoadOk = false;

                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element && reader.Name == "ispostprocessing")
                    {
                        reader.Read();
                        if (reader.NodeType == XmlNodeType.Text)
                        {
                            try
                            {
                                loadPostProcessing = Convert.ToBoolean(reader.Value);
                            }
                            catch
                            {
                                return;
                            }

                            isLoadOk = true;
                            break;
                        }
                    }
                }
            }
        }

        #endregion

        #region Save Settings

        private void SaveSettings()
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.ConformanceLevel = ConformanceLevel.Document;
            settings.Indent = true;
            settings.CloseOutput = true;
            settings.CheckCharacters = true;

            using (XmlWriter writer = XmlWriter.Create(settingsFile, settings))
            {
                writer.WriteStartDocument();
                writer.WriteComment(" " + Application.ProductVersion + " ");
                writer.WriteComment(" DISPLAY SETTINGS ");
                writer.WriteComment(" do not manually edit this file ");
                writer.WriteStartElement("settings");
                writer.WriteStartElement("launcher");
                writer.WriteElementString("reslindex", cmbResolution.SelectedIndex.ToString());
                writer.WriteElementString("isfullscr", ckbFullScreen.Checked.ToString());
                writer.WriteElementString("isantialiasing", ckbAntiAliasing.Checked.ToString());
                writer.WriteElementString("ispostprocessing", ckbPostProcessing.Checked.ToString());
                writer.WriteEndElement();
                writer.WriteStartElement("game");                
                writer.WriteElementString("width", ((DisplayResolution)cmbResolution.SelectedItem).Width.ToString());
                writer.WriteElementString("height", ((DisplayResolution)cmbResolution.SelectedItem).Height.ToString());
                writer.WriteElementString("mode", ckbFullScreen.Checked.ToString());
                writer.WriteElementString("antialiasing", ckbAntiAliasing.Checked.ToString());
                writer.WriteElementString("postprocessing", ckbPostProcessing.Checked.ToString());
                writer.WriteEndElement();
                writer.WriteEndDocument();
                writer.Flush();
            }
        }

        #endregion

        #region Launcher Configuration
                
        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        public Launcher()
        {
            #region Launcher Configuration

            InitializeComponent();

            GetDisplayModes();

            LoadSettings();

            // label showing application version
            lblVersion.Text = Application.ProductVersion;

            // ComboBox showing all available display resolutions
            cmbResolution.DataSource = systemDisplayResl;
            cmbResolution.DisplayMember = "Resolution";
            cmbResolution.SelectedIndex = (isLoadOk) ? loadReslIndex : defaultReslIndex;

            // by default, full screen mode            
            ckbFullScreen.Checked = (isLoadOk) ? loadDisplayMode : defaultDisplayMode;

            // by default, antialiasing and postprocessing active
            ckbAntiAliasing.Checked = (isLoadOk) ? loadAntiAliasing : defaultAntiAliasing;
            ckbPostProcessing.Checked = (isLoadOk) ? loadPostProcessing : defaultPostProcessing;

            #endregion
        }

        #endregion

        #region Event Handlers

        // PLAY
        private void btnPlay_Click(object sender, EventArgs e)
        {
            #region Save Settings

            SaveSettings();

            #endregion

            #region StarFox Launch

            ProcessStartInfo startInfo = new ProcessStartInfo();
            // executable name
            startInfo.FileName = "StarFox.exe";
            // windows style
            startInfo.WindowStyle = ProcessWindowStyle.Normal;          

            // close the launcher
            Close();

            using (Process exeprocess = Process.Start(startInfo)) { }

            #endregion
        }

        // EXIT
        private void btnExit_Click(object sender, EventArgs e)
        {
            Close();
        }

        // DEFAULT
        private void btnDefault_Click(object sender, EventArgs e)
        {
            // reset launcher items
            cmbResolution.SelectedIndex = defaultReslIndex;
            ckbFullScreen.Checked = defaultDisplayMode;
            ckbAntiAliasing.Checked = defaultAntiAliasing;
            ckbPostProcessing.Checked = defaultPostProcessing;
        }

        // RESOLUTION
        private void cmbResolution_SelectedIndexChanged(object sender, EventArgs e)
        {
        }

        // FULLSCREEN?
        private void ckbFullScreen_CheckedChanged(object sender, EventArgs e)
        {
        }

        // ANTIALIASING?
        private void ckbAntiAliasing_CheckedChanged(object sender, EventArgs e)
        {
        }

        // POSTPROCESSING?
        private void ckbPostProcessing_CheckedChanged(object sender, EventArgs e)
        {
        }

        #endregion
    }
}
